<?php
/**
 * @file WCTimer.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-04-30 02:04:27 +0000 (Tue, 30 Apr 2013) $
 *
 * $Id: WCTimer.php 63 2013-04-30 02:04:27Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0-BETA1/includes/WCTimer.php $
 */

/**
 * @class WCTimer
 */
class WCTimer {
	/**
	 * @var WCTimer
	 */
	protected static	$_Instance;

	/*
	 * @var int
	*/
	protected	$_globalTimer		= 0;
	protected	$_globalTimerRunning	= false;
	protected	$_onShell		= false;
	protected	$_timers		= array();
	protected	$_timersRunning		= array();

	protected function __construct() {
		$this->_onShell = !empty($_SERVER['SHELL']);
	}
	public function __destruct() {
	}
	/**
	 * Prevent users to clone the instance.
	 */
	public function __clone() {
		trigger_error(__CLASS__.": Clone is not allowed.", E_USER_ERROR);
	}

	//
	// Public methods.
	public function clearStats() {
		global	$wcDefaults;

		if($wcDefaults["stats-max-time"] > 0) {
			global	$wcDatabaseAccess;

			$db		= WCConnection::Instance();
			$dbprefix	= $wcDatabaseAccess['prefix'];

			$stmt	= null;
			$stmtId	= __CLASS__."::".__FUNCTION__;
			if($db->has($stmtId)) {
				$stmt = $db->get($stmtId);
			} else {
				$query = "delete from {$dbprefix}stats_timer\n";
				$query.= "where       st_t_sdate < :sdate\n";

				$stmt = $db->prepare($stmtId, $query);
			}

			$params = array(":sdate" => date("Ymd",strtotime("-{$wcDefaults["stats-max-time"]} day",time())));

			$stmt->execute($params);
		}
	}
	public function globalTimer(&$running=null) {
		$out = -1;

		if($this->_globalTimer) {
			$out		= ceil($this->_globalTimer * 1000);
			$running	= $this->_globalTimerRunning;
		} else {
			trigger_error(__CLASS__."::".__FUNCTION__."(): Global timer was never used", E_USER_ERROR);
		}

		return $out;
	}
	public function saveGlobal($caller="no-caller") {
		global	$wcDefaults;

		$this->stopGlobal();
		if($wcDefaults["stats-max-time"] > 0) {
			$this->clearStats();

			global	$wcDatabaseAccess;

			$db		= WCConnection::Instance();
			$dbprefix	= $wcDatabaseAccess['prefix'];

			$stmt	= null;
			$stmtId	= __CLASS__."::".__FUNCTION__;
			if($db->has($stmtId)) {
				$stmt = $db->get($stmtId);
			} else {
				$query = "insert\n";
				$query.= "        into {$dbprefix}stats_timer (\n";
				$query.= "                st_t_code, st_t_action, st_t_caller, st_t_group, st_t_collection,\n";
				$query.= "                st_t_tag, st_t_directory, st_t_comic, st_t_rule, st_t_maximum,\n";
				$query.= "                st_t_minimum, st_t_average, st_t_times, st_t_method, st_t_sdate)\n";
				$query.= "        values (:code, :action, :caller, :group, :collection,\n";
				$query.= "                :tag, :directory, :comic, :rule, :time,\n";
				$query.= "                :time, :time, 1, :method, date_format(now(),'%Y%m%d'))\n";
				$query.= "        on duplicate key\n";
				$query.= "                update  st_t_maximum = greatest(st_t_maximum, :time),\n";
				$query.= "                        st_t_minimum = least(st_t_minimum, :time),\n";
				$query.= "                        st_t_average = round((st_t_average + :time) / 2),\n";
				$query.= "                        st_t_times   = st_t_times + 1\n";

				$stmt = $db->prepare($stmtId, $query);
			}

			global	$wcAction;
			global	$wcGroup;
			global	$wcCollection;
			global	$wcTag;
			global	$wcDirectory;
			global	$wcComic;
			global	$wcRule;

			$code = "UNKNOWN";
			if(!$this->_onShell) {
				$code = "{$_SERVER["SCRIPT_NAME"]}?{$_SERVER["QUERY_STRING"]}";
			} else {
				$code	= $_SERVER["SCRIPT_NAME"];
			}
			$params = array(
					":code"		=> $code,
					":action"	=> $wcAction     ? $wcAction         : "UNKNOWN",
					":caller"	=> $caller,

					":group"	=> $wcGroup      ? $wcGroup->id      : null,
					":collection"	=> $wcCollection ? $wcCollection->id : null,
					":tag"		=> $wcTag        ? $wcTag->id        : null,
					":directory"	=> $wcDirectory  ? $wcDirectory->id  : null,
					":comic"	=> $wcComic      ? $wcComic->id      : null,
					":rule"		=> $wcRule       ? $wcRule->id       : null,

					":time"		=> $this->globalTimer(),
					":method"	=> $_SERVER["REQUEST_METHOD"]
			);

			$stmt->execute($params);
		}
	}
	public function start($id) {
		if(!isset($this->_timersRunning[$id]) || !$this->_timersRunning[$id]) {
			$this->_timersRunning[$id]	= true;
			$this->_timers[$id]		= microtime(true);
		} else {
			trigger_error(__CLASS__."::".__FUNCTION__."(): Timer '{$id}' in already running", E_USER_ERROR);
		}
	}
	public function startGlobal() {
		if(!$this->_globalTimerRunning) {
			$this->_globalTimerRunning	= true;
			$this->_globalTimer		= microtime(true);
		} else {
			trigger_error(__CLASS__."::".__FUNCTION__."(): Global timer already started", E_USER_ERROR);
		}
	}
	public function stop($id) {
		if(isset($this->_timersRunning[$id]) && $this->_timersRunning[$id]) {
			$this->_timersRunning[$id]	= false;
			$this->_timers[$id]		= microtime(true) - $this->_timers[$id];
		} elseif(!isset($this->_timersRunning[$id])) {
			trigger_error(__CLASS__."::".__FUNCTION__."(): Timer '{$id}' was never started", E_USER_ERROR);
		} else {
			trigger_error(__CLASS__."::".__FUNCTION__."(): Timer '{$id}' in not running", E_USER_ERROR);
		}

		return $this->timer($id);
	}
	public function stopGlobal() {
		if($this->_globalTimerRunning) {
			$this->_globalTimerRunning	= false;
			$this->_globalTimer		= microtime(true) - $this->_globalTimer;
		} else {
			trigger_error(__CLASS__."::".__FUNCTION__."(): Global timer is not started", E_USER_ERROR);
		}

		return $this->globalTimer($id);
	}
	public function timer($id, &$running=null) {
		$out		= 0;
		$running	= null;

		if(isset($this->_timersRunning[$id])) {
			$out		= ceil($this->_timers[$id] * 1000);
			$running	= $this->_timersRunning[$id];
		}

		return $out;
	}

	//
	// Protected methods.

	//
	// Public class methods.
	public static function Instance() {
		if(!isset(self::$_Instance)) {
			$c = __CLASS__;
			self::$_Instance = new $c();
		}

		return self::$_Instance;
	}
}

?>